home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / oldwish / old / wishGather.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-03  |  27.5 KB  |  1,100 lines

  1. /* 
  2.  * fsflatGather.c --
  3.  *
  4.  *    Gathering and sorting file names.  Putting them in
  5.  *    data structures.
  6.  *
  7.  * Copyright 1987 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: fsflatGather.c,v 1.1 88/10/03 12:47:47 mlgray Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sys/types.h>
  24. #include <sys/stat.h>
  25. #include <sys/dir.h>
  26. #include <errno.h>
  27. #include "sx.h"
  28. #include "string.h"
  29. #include "util.h"
  30. #include "fsflatInt.h"
  31.  
  32. /* ClientData for scandir select proc's */
  33. static    ClientData    scanData;
  34.  
  35. /* used before defined */
  36. extern    Boolean    SelectFiles();
  37. extern    int    AlphaForwards();
  38. extern    int    AlphaReverse();
  39. extern    int    AtimeForwards();
  40. extern    int    AtimeReverse();
  41. extern    int    CtimeForwards();
  42. extern    int    CtimeReverse();
  43. extern    int    MtimeForwards();
  44. extern    int    MtimeReverse();
  45. extern    int    DtimeForwards();
  46. extern    int    DtimeReverse();
  47. extern    int    SizeForwards();
  48. extern    int    SizeReverse();
  49. extern    int    AtimeSort();
  50. extern    int    MtimeSort();
  51. extern    int    DtimeSort();
  52. extern    int    SizeSort();
  53.  
  54.  
  55. /*
  56.  *----------------------------------------------------------------------
  57.  *
  58.  * FsflatGatherNames --
  59.  *
  60.  *    Using scandir() and a bunch of rules and call-back thingies,
  61.  *    gather the appropriate names into the appropriate places.
  62.  *
  63.  * Results:
  64.  *    TCL_OK if all went well.  Some TCL error if not.
  65.  *
  66.  * Side effects:
  67.  *    The names are gathered and stuff is allocated.
  68.  *
  69.  *----------------------------------------------------------------------
  70.  */
  71. int
  72. FsflatGatherNames(aWindow)
  73.     FsflatWindow    *aWindow;
  74. {
  75.     int        nitems;
  76.     struct    direct    **namelist;
  77.     int        (*compareProc)();
  78.     int        i;
  79.     FsflatFile    *tmpPtr, *backTmpPtr;
  80.     FsflatGroup    *grpPtr;
  81.     int        result;
  82.     Boolean    getAttrsP = FALSE;
  83.     struct    stat    attrs;
  84.  
  85.     if (aWindow->groupList == NULL) {
  86.     /* get it out of the file */
  87. #ifdef NOTDEF
  88.     Sx_Panic(fsflatDisplay,
  89.         "FsflatGatherNames: Should source .wish file, but can't.");
  90. #endif NOTDEF
  91. #ifdef NOTDEF
  92.     FsflatReadRules(aWindow, name);
  93. #endif NOTDEF
  94.     }
  95.     if (aWindow->groupList == NULL) {
  96.     /*
  97.      * There wasn't a file, select everything (or should the default
  98.      * be to select nothing?
  99.      */
  100.     aWindow->groupList = (FsflatGroup *) malloc(sizeof (FsflatGroup));
  101.     aWindow->groupList->myColumn = -1;
  102.     aWindow->groupList->headerWindow = UNINITIALIZED;
  103.     aWindow->groupList->x = aWindow->groupList->y = -1;
  104.     aWindow->groupList->width = aWindow->groupList->height = -1;
  105.     aWindow->groupList->entry_x = aWindow->groupList->entry_y =
  106.         aWindow->groupList->entry_width = -1;
  107.     aWindow->groupList->fileList = NULL;
  108.     aWindow->groupList->defType = COMPARISON;
  109.     aWindow->groupList->rule = Util_Strcpy(NULL, "*");
  110.     aWindow->groupList->groupBindings = NULL;
  111.     aWindow->groupList->length = -1;
  112.     aWindow->groupList->selectedP = FALSE;
  113.     aWindow->groupList->highlightP = FALSE;
  114.     aWindow->groupList->nextPtr = NULL;
  115.  
  116.     aWindow->numElements = UNINITIALIZED;
  117.     aWindow->numGroups = 1;
  118.     aWindow->numHiddenGroups = 0;
  119.     }
  120.     if (aWindow->numElements >= 0) {
  121.     /*
  122.      * For now, this means this has already been set up, since there's
  123.      * no garbage collection yet.
  124.      */
  125.     return TCL_OK;
  126.     }
  127.     FsflatGetCompareProc(aWindow, &compareProc, FALSE);
  128.     getAttrsP = FSFLAT_ATTR_NECESSARY_P; 
  129.  
  130.     scanData = (ClientData) aWindow;
  131.     nitems = scandir(aWindow->dir, &namelist, SelectFiles, compareProc);
  132.     /*
  133.      * I use Stat_GetMsg here.  Am I doing it correctly with errno?
  134.      */
  135.     if (nitems < 0) {
  136.     sprintf(aWindow->interp->result, "%s %s %s %s.  %s %s",
  137.         "Directory scan failed in", aWindow->dir, "with error",
  138.         Stat_GetMsg(errno),
  139.         "Either the directory doesn't exist, or it",
  140.         "is unreadable, or we've run out of memory");
  141.     return TCL_ERROR;
  142.     }
  143.     /*
  144.      * For each file, run through all the groups putting a copy of the file
  145.      * into the group if it matches the rule for that group.  This allows
  146.      * one file to show up in all groups that can select it.  If files should
  147.      * only show up in one place, then skip to the next file after we've
  148.      * found one group for it.  Right now, I use the first policy.  Maybe
  149.      * this should be an option.
  150.      *
  151.      * Since the files are in proper sorted order already and I run through
  152.      * them in order, they will come out in proper sorted order inside the
  153.      * groups.
  154.      *
  155.      * NOTE:  This may be way too slow to use Pattern_Match() in 2 passes
  156.      * like this.
  157.      */
  158.     aWindow->numElements = 0;        /* since it's initialized to -1 */
  159.     aWindow->numHiddenGroups = 0;
  160.     for (i = 0; i < nitems; i++) {
  161.     if (getAttrsP) {
  162.         /*
  163.          * If the files were sorted by something involving an attribute,
  164.          * then there should be a way in the sort routines to cache that
  165.          * info so we don't do a second GetAttributes()'s here...
  166.          * This means dealing with the garbage collection aspects too.
  167.          */
  168.         if (lstat(namelist[i]->d_name, &attrs)
  169.             != 0) {
  170.         char    buffer[MAXPATHLEN];
  171.         sprintf(fsflatErrorMsg, "%s %s.  %s %s.  %s %s.",
  172.             "Couldn't get attributes for file",
  173.             namelist[i]->d_name,
  174.             "Error was",
  175.             Stat_GetMsg(errno),
  176.             "Current dir is",
  177.             getwd(buffer) == NULL ? "NULL" : buffer);
  178.         Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  179.             fsflatErrorMsg,
  180.             NULL, TRUE, "Skip offending file", (char *) NULL);
  181.         continue;
  182.         }
  183.     }
  184.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  185.         grpPtr = grpPtr->nextPtr) {
  186.         result = Pattern_Match(grpPtr->rule, namelist[i]->d_name);
  187.         if (result == 0) {        /* it matched */
  188.         tmpPtr = (FsflatFile *) malloc(sizeof (FsflatFile));
  189.         tmpPtr->name = Util_Strcpy(NULL, namelist[i]->d_name);
  190.         if (getAttrsP) {
  191.             tmpPtr->attrPtr = (struct    stat *)
  192.                 malloc(sizeof (struct    stat));
  193.             *(tmpPtr->attrPtr) = attrs;
  194.         } else {
  195.             tmpPtr->attrPtr = NULL;
  196.         }
  197.         tmpPtr->length = -1;
  198.         tmpPtr->x = tmpPtr->y = -1;
  199.         tmpPtr->myColumn = -1;
  200.         tmpPtr->selectedP = FALSE;
  201.         tmpPtr->lineP = FALSE;
  202.         tmpPtr->highlightP = FALSE;
  203.         tmpPtr->myGroupPtr = grpPtr;
  204.         tmpPtr->nextPtr = NULL;
  205.         if (grpPtr->fileList == NULL) {
  206.             grpPtr->fileList = tmpPtr;
  207.         } else {
  208.             /* add file to end of list */
  209.             for (backTmpPtr = grpPtr->fileList;
  210.                 backTmpPtr->nextPtr != NULL;
  211.                 backTmpPtr = backTmpPtr->nextPtr) {
  212.             /* do nothing */
  213.             }
  214.             backTmpPtr->nextPtr = tmpPtr;
  215.         }
  216.         aWindow->numElements++;
  217.         } else if (result < 0) {
  218.         /*
  219.          * I check the rules as they are created, or the following
  220.          * would cause a billion notifiers!  This is just for extreme
  221.          * caution...
  222.          */
  223.         sprintf(fsflatErrorMsg, "The rule %s contains an error.",
  224.             grpPtr->rule);
  225.         Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  226.             fsflatErrorMsg, NULL,
  227.             TRUE, "Continue", NULL);
  228.         }
  229.     }
  230.     }
  231.     if (aWindow->hideEmptyGroupsP) {
  232.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  233.         grpPtr = grpPtr->nextPtr) {
  234.         if (grpPtr->fileList == NULL) {
  235.         aWindow->numHiddenGroups++;
  236.         }
  237.     }
  238.     }
  239.     /*
  240.      * total number of things that could be displayed is the number of files
  241.      * plus the number of visible group headers plus the number of spaces
  242.      * between visible groups.
  243.      */
  244.     aWindow->totalDisplayEntries = aWindow->numElements +
  245.         (2 * (aWindow->numGroups - aWindow->numHiddenGroups)) - 1;
  246.     free_scandir(nitems, &namelist);
  247.  
  248.     return TCL_OK;
  249. }
  250.  
  251. typedef    struct    {
  252.     FsflatWindow    *aWindow;
  253.     FsflatGroup        *grpPtr;
  254. } GatherInfo;
  255.  
  256.  
  257. /*
  258.  *----------------------------------------------------------------------
  259.  *
  260.  * FsflatGatherSingleGroup --
  261.  *
  262.  *    Using scandir() and a bunch of rules and call-back thingies,
  263.  *    gather the appropriate names into the appropriate places.
  264.  *
  265.  * Results:
  266.  *    TCL_OK if all went well.  Some TCL error if not.
  267.  *
  268.  * Side effects:
  269.  *    The names are gathered and stuff is allocated.
  270.  *
  271.  *----------------------------------------------------------------------
  272.  */
  273. int
  274. FsflatGatherSingleGroup(aWindow, grpPtr)
  275.     FsflatWindow    *aWindow;
  276.     FsflatGroup        *grpPtr;
  277. {
  278.     Boolean    getAttrsP = FALSE;
  279.     int        nitems;
  280.     struct    direct    **namelist;
  281.     int        (*compareProc)();
  282.     struct    stat    attrs;
  283.     FsflatFile    *tmpPtr, *backTmpPtr;
  284.     extern    Boolean    SelectGroupFiles();    /* forward reference */
  285.     int        i;
  286.     GatherInfo    gatherInfo;
  287.  
  288.     FsflatGetCompareProc(aWindow, &compareProc, FALSE);
  289.     getAttrsP = FSFLAT_ATTR_NECESSARY_P; 
  290.  
  291.     gatherInfo.aWindow = aWindow;
  292.     gatherInfo.grpPtr = grpPtr;
  293.     scanData = (ClientData) &gatherInfo;
  294.     nitems = scandir(aWindow->dir, &namelist, SelectGroupFiles, compareProc);
  295.     if (nitems < 0) {
  296.     sprintf(aWindow->interp->result, "%s %s %s %s.  %s %s",
  297.         "Directory scan failed in", aWindow->dir, "with error",
  298.         Stat_GetMsg(errno),
  299.         "Either the direcotry doesn't exist, or it",
  300.         "is unreadable, or we've run out of memory");
  301.     return TCL_ERROR;
  302.     }
  303.     /* since they're initialized to -1 */
  304.     if (aWindow->numElements == UNINITIALIZED) {
  305.     aWindow->numElements = 0;
  306.     }
  307.     if (aWindow->numHiddenGroups == UNINITIALIZED) {
  308.     aWindow->numHiddenGroups = 0;
  309.     }
  310.     for (i = 0; i < nitems; i++) {
  311.     if (getAttrsP) {
  312.         /*
  313.          * If the files were sorted by something involving an attribute,
  314.          * then there should be a way in the sort routines to cache that
  315.          * info so we don't do a second GetAttributes()'s here...
  316.          * This means dealing with the garbage collection aspects too.
  317.          */
  318.         if (lstat(namelist[i]->d_name, &attrs)
  319.             != 0) {
  320.         char    buffer[MAXPATHLEN];
  321.         sprintf(fsflatErrorMsg, "%s %s.  %s %s.  %s %s.",
  322.             "Couldn't get attributes for file",
  323.             namelist[i]->d_name,
  324.             "Error was",
  325.             Stat_GetMsg(errno),
  326.             "Current dir is",
  327.             getwd(buffer) == NULL ? "NULL" : buffer);
  328.         Sx_Notify(fsflatDisplay, aWindow->surroundingWindow, -1, -1, 0,
  329.             fsflatErrorMsg,
  330.             NULL, TRUE, "Leave attributes blank", (char *) NULL);
  331.         bzero(&attrs, sizeof (struct    stat));;
  332.         }
  333.     }
  334.     tmpPtr = (FsflatFile *) malloc(sizeof (FsflatFile));
  335.     tmpPtr->name = Util_Strcpy(NULL, namelist[i]->d_name);
  336.     if (getAttrsP) {
  337.         tmpPtr->attrPtr = (struct    stat *)
  338.             malloc(sizeof (struct    stat));
  339.         *(tmpPtr->attrPtr) = attrs;
  340.     } else {
  341.         tmpPtr->attrPtr = NULL;
  342.     }
  343.     tmpPtr->length = -1;
  344.     tmpPtr->x = tmpPtr->y = -1;
  345.     tmpPtr->myColumn = -1;
  346.     tmpPtr->selectedP = FALSE;
  347.     tmpPtr->lineP = FALSE;
  348.     tmpPtr->highlightP = FALSE;
  349.     tmpPtr->myGroupPtr = grpPtr;
  350.     tmpPtr->nextPtr = NULL;
  351.     if (grpPtr->fileList == NULL) {
  352.         grpPtr->fileList = tmpPtr;
  353.     } else {
  354.         /* add file to end of list */
  355.         for (backTmpPtr = grpPtr->fileList;
  356.             backTmpPtr->nextPtr != NULL;
  357.             backTmpPtr = backTmpPtr->nextPtr) {
  358.         /* do nothing */
  359.         }
  360.         backTmpPtr->nextPtr = tmpPtr;
  361.     }
  362.     aWindow->numElements++;
  363.     }
  364.     if (aWindow->numGroups == UNINITIALIZED) {
  365.     aWindow->numGroups = 1;
  366.     aWindow->numHiddenGroups = 0;
  367.     } else {
  368.     aWindow->numGroups++;
  369.     }
  370.     if (aWindow->hideEmptyGroupsP) {
  371.     if (grpPtr->fileList == NULL) {
  372.         aWindow->numHiddenGroups++;
  373.     }
  374.     }
  375.     /*
  376.      * Total number of things that could be displayed is the number of files
  377.      * plus the number of visible group headers plus the number of spaces
  378.      * between visible groups.
  379.      */
  380.     aWindow->totalDisplayEntries = aWindow->numElements +
  381.         (2 * (aWindow->numGroups - aWindow->numHiddenGroups)) - 1;
  382.     free_scandir(nitems, &namelist);
  383.  
  384.     return TCL_OK;
  385. }
  386.  
  387.  
  388. /*
  389.  *----------------------------------------------------------------------
  390.  *
  391.  * SelectFiles --
  392.  *
  393.  *    Routine passed to scandir(). 
  394.  *
  395.  * Results:
  396.  *    Return TRUE or FALSE depending
  397.  *    upon whether or not there's a group with a rule that would
  398.  *    select this the given file.
  399.  *
  400.  * Side effects:
  401.  *    None.
  402.  *
  403.  *----------------------------------------------------------------------
  404.  */
  405. Boolean
  406. SelectFiles(entryPtr)
  407.     struct    direct    *entryPtr;
  408. {
  409.     FsflatWindow    *aWindow;
  410.     FsflatGroup        *grpPtr;
  411.     int            result;
  412.  
  413.     aWindow = (FsflatWindow *) scanData;
  414.     for (grpPtr = aWindow->groupList; grpPtr != NULL;
  415.         grpPtr = grpPtr->nextPtr) {
  416.     result = Pattern_Match(grpPtr->rule, entryPtr->d_name);
  417.     if (result == 0) {
  418.         break;
  419.     } else if (result < 0) {
  420.         /*
  421.          * I must check the rules as they are created, or the following
  422.          * would cause a billion notifiers!
  423.          */
  424.         sprintf(fsflatErrorMsg, "The rule %s contains an error.",
  425.         grpPtr->rule);
  426.         Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  427.             fsflatErrorMsg, NULL, TRUE, "Continue", NULL);
  428.     }
  429.     }
  430.     if (grpPtr == NULL) {
  431.     return FALSE;
  432.     }
  433.     return TRUE;
  434. }
  435.  
  436.  
  437. /*
  438.  *----------------------------------------------------------------------
  439.  *
  440.  * SelectGroupFiles --
  441.  *
  442.  *    Routine passed to scandir() for selecting files for a single group. 
  443.  *
  444.  * Results:
  445.  *    Return TRUE or FALSE depending
  446.  *    upon whether or not the given group rule will select the given file.
  447.  *
  448.  * Side effects:
  449.  *    None.
  450.  *
  451.  *----------------------------------------------------------------------
  452.  */
  453. Boolean
  454. SelectGroupFiles(entryPtr)
  455.     struct    direct    *entryPtr;
  456. {
  457.     FsflatGroup        *grpPtr;
  458.     int            result;
  459.     FsflatWindow    *aWindow;
  460.  
  461.     aWindow = ((GatherInfo *) scanData)->aWindow;
  462.     grpPtr = ((GatherInfo *) scanData)->grpPtr;
  463.     if (grpPtr->defType == COMPARISON) {
  464.     result = Pattern_Match(grpPtr->rule, entryPtr->d_name);
  465.     if (result == 0) {
  466.         return TRUE;
  467.     } else if (result < 0) {
  468.         sprintf(fsflatErrorMsg, "The rule %s contains an error.",
  469.         grpPtr->rule);
  470.         Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  471.             fsflatErrorMsg, NULL, TRUE, "Continue", NULL);
  472.     }
  473.     return FALSE;
  474.     }
  475.     if (grpPtr->defType != PROC) {
  476.     Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  477.         "unknown type of rule definition", NULL,
  478.         TRUE, "Continue", NULL);
  479.     return FALSE;
  480.     }
  481.     if (FsflatDoTclSelect(aWindow->interp, grpPtr->rule, entryPtr->d_name,
  482.         &result) != TCL_OK) {
  483.     Sx_Notify(fsflatDisplay, aWindow->displayWindow, -1, -1, 0,
  484.         aWindow->interp->result, NULL, TRUE, "Continue", NULL);
  485.     return FALSE;
  486.     }
  487.     return result;
  488. }
  489.  
  490.  
  491. /*
  492.  *----------------------------------------------------------------------
  493.  *
  494.  * FsflatDoTclSelect --
  495.  *
  496.  *    Execute the tcl rule procName on the fileName arg and determine
  497.  *    whether the file matches the rule.
  498.  *
  499.  * Results:
  500.  *    TCL_OK if things work ok, and TCL_ERROR if not.  If the routine
  501.  *    returns TCL_OK, then boolean value
  502.  *    determining whether the file matches the rule is returned in the
  503.  *    selectValPtr parameter.
  504.  *
  505.  * Side effects:
  506.  *    None.
  507.  *
  508.  *----------------------------------------------------------------------
  509.  */
  510. int
  511. FsflatDoTclSelect(interp, procName, arg, selectValPtr)
  512.     Tcl_Interp        *interp;
  513.     char        *procName;
  514.     char        *arg;
  515.     int            *selectValPtr;
  516. {
  517.     char    *buffer;
  518.     char    *cPtr;
  519.  
  520.     if (procName == NULL || arg == NULL) {
  521.     strcpy(interp->result,
  522.         "Null procedure name or argument for file selection");
  523.     return TCL_ERROR;
  524.     }
  525.     buffer = (char *) malloc(strlen(procName) + strlen(arg) + 2);
  526.     sprintf(buffer, "%s %s", procName, arg);
  527.     if (Tcl_Eval(interp, buffer, '\0', NULL) != TCL_OK) {
  528.     sprintf(interp->result,
  529.         "Something is wrong with the rule definition %s.", procName);
  530.     free(buffer);
  531.     return TCL_ERROR;
  532.     }
  533.     free(buffer);
  534.     if ((*selectValPtr = strtol(interp->result, &cPtr, 10)) == 0
  535.         && cPtr == interp->result) {
  536.     sprintf(interp->result, "Bad proc definition %s", procName);
  537.     return TCL_ERROR;
  538.     }
  539.     if (*selectValPtr < 0) {
  540.     sprintf(interp->result, "proc %s returned an error value", procName);
  541.     return TCL_ERROR;
  542.     }
  543.     /* reverse the meaning, since pattern match returns 0 for success... */
  544.     if (*selectValPtr == 0) {
  545.     *selectValPtr = 1;
  546.     } else {
  547.     *selectValPtr = 0;
  548.     }
  549.     return TCL_OK;
  550. }
  551.  
  552.  
  553. /*
  554.  *----------------------------------------------------------------------
  555.  *
  556.  * AlphaForwards --
  557.  *
  558.  *    Compare two files for alphabetical order.
  559.  *
  560.  * Results:
  561.  *    Negative if the first is before the second.  Zero if they are the
  562.  *    same.  Positive if the first is after the second.
  563.  *
  564.  * Side effects:
  565.  *    None.
  566.  *
  567.  *----------------------------------------------------------------------
  568.  */
  569. int
  570. AlphaForwards(first, second)
  571.     struct    direct    **first, **second;
  572. {
  573.     return alphasort(first, second);
  574. }
  575.  
  576.  
  577. /*
  578.  *----------------------------------------------------------------------
  579.  *
  580.  * AlphaReverse --
  581.  *
  582.  *    Compare two files for reverse alphabetical order.
  583.  *
  584.  * Results:
  585.  *    Negative if the first is before the second.  Zero if they are the
  586.  *    same.  Positive if the first is after the second.
  587.  *
  588.  * Side effects:
  589.  *    None.
  590.  *
  591.  *----------------------------------------------------------------------
  592.  */
  593. int
  594. AlphaReverse(first, second)
  595.     struct    direct    **first, **second;
  596. {
  597.     return (-alphasort(first, second));
  598. }
  599.  
  600.  
  601. int
  602. AtimeForwards(first, second)
  603.     struct    direct    **first, **second;
  604. {
  605.     return AtimeSort(first, second);
  606. }
  607.  
  608. int
  609. AtimeReverse(first, second)
  610.     struct    direct    **first, **second;
  611. {
  612.     return (-AtimeSort(first, second));
  613. }
  614.  
  615. #ifdef NOTDEF
  616. int
  617. CtimeForwards(first, second)
  618.     struct    direct    **first, **second;
  619. {
  620.     return CtimeSort(first, second);
  621. }
  622.  
  623. int
  624. CtimeReverse(first, second)
  625.     struct    direct    **first, **second;
  626. {
  627.     return (-CtimeSort(first, second));
  628. }
  629. #endif /* NOTDEF */
  630.  
  631. int
  632. MtimeForwards(first, second)
  633.     struct    direct    **first, **second;
  634. {
  635.     return MtimeSort(first, second);
  636. }
  637.  
  638. int
  639. MtimeReverse(first, second)
  640.     struct    direct    **first, **second;
  641. {
  642.     return (-MtimeSort(first, second));
  643. }
  644.  
  645. int
  646. DtimeForwards(first, second)
  647.     struct    direct    **first, **second;
  648. {
  649.     return DtimeSort(first, second);
  650. }
  651.  
  652. int
  653. DtimeReverse(first, second)
  654.     struct    direct    **first, **second;
  655. {
  656.     return (-DtimeSort(first, second));
  657. }
  658.  
  659. int
  660. SizeForwards(first, second)
  661.     struct    direct    **first, **second;
  662. {
  663.     return SizeSort(first, second);
  664. }
  665.  
  666. int
  667. SizeReverse(first, second)
  668.     struct    direct    **first, **second;
  669. {
  670.     return (-SizeSort(first, second));
  671. }
  672.  
  673. static int
  674. FileAlphaSort(file1, file2)
  675.     FsflatFile    **file1;
  676.     FsflatFile    **file2;
  677. {
  678.     return strcmp((*file1)->name, (*file2)->name);
  679. }
  680.  
  681. static int
  682. FileAlphaReverseSort(file1, file2)
  683.     FsflatFile    **file1;
  684.     FsflatFile    **file2;
  685. {
  686.     return (-strcmp((*file1)->name, (*file2)->name));
  687. }
  688.  
  689. static int
  690. AtimeCompare(attrs1, attrs2)
  691.     struct    stat    *attrs1;
  692.     struct    stat    *attrs2;
  693. {
  694.     if (attrs1->st_atime > attrs2->st_atime) {
  695.     return -1;
  696.     }
  697.     if (attrs1->st_atime< attrs2->st_atime) {
  698.     return 1;
  699.     }
  700. #ifdef NOTDEF
  701.     /*
  702.      * What to do about this?  Sprite gives microseconds as well as
  703.      * seconds...
  704.      */
  705.     if (attrs1->st_atime.microseconds > attrs2->st_atime.microseconds) {
  706.     return -1;
  707.     }
  708.     if (attrs1->st_atime.microseconds < attrs2->st_atime.microseconds) {
  709.     return 1;
  710.     }
  711. #endif /* NOTDEF */
  712.     return 0;
  713. }
  714.  
  715. static int
  716. FileAtimeSort(file1, file2)
  717.     FsflatFile    **file1;
  718.     FsflatFile    **file2;
  719. {
  720.     return AtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  721. }
  722.  
  723. static int
  724. FileAtimeReverseSort(file1, file2)
  725.     FsflatFile    **file1;
  726.     FsflatFile    **file2;
  727. {
  728.     return (-AtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  729. }
  730.  
  731. static    int
  732. AtimeSort(d1, d2)
  733.     struct    direct    **d1, **d2;
  734. {
  735.     struct    stat    attrs1;
  736.     struct    stat    attrs2;
  737.  
  738.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  739.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  740.         (*d1)->d_name);
  741.     /* Is panic the right thing? */
  742.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  743.     }
  744.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  745.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  746.         (*d2)->d_name);
  747.     /* Is panic the right thing? */
  748.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  749.     }
  750.     return AtimeCompare(&attrs1, &attrs2);
  751.  
  752. }
  753.  
  754. #ifdef NOTDEF
  755. static int
  756. CtimeCompare(attrs1, attrs2)
  757.     struct    stat    *attrs1;
  758.     struct    stat    *attrs2;
  759. {
  760.     if (attrs1->createTime.seconds > attrs2->createTime.seconds) {
  761.     return -1;
  762.     }
  763.     if (attrs1->createTime.seconds < attrs2->createTime.seconds) {
  764.     return 1;
  765.     }
  766.     if (attrs1->createTime.microseconds > attrs2->createTime.microseconds) {
  767.     return -1;
  768.     }
  769.     if (attrs1->createTime.microseconds < attrs2->createTime.microseconds) {
  770.     return 1;
  771.     }
  772.     return 0;
  773. }
  774.  
  775. static int
  776. FileCtimeSort(file1, file2)
  777.     FsflatFile    **file1;
  778.     FsflatFile    **file2;
  779. {
  780.     return CtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  781. }
  782.  
  783. static int
  784. FileCtimeReverseSort(file1, file2)
  785.     FsflatFile    **file1;
  786.     FsflatFile    **file2;
  787. {
  788.     return (-CtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  789. }
  790.  
  791. static    int
  792. CtimeSort(d1, d2)
  793.     struct    direct    **d1, **d2;
  794. {
  795.     struct    stat    attrs1;
  796.     struct    stat    attrs2;
  797.  
  798.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  799.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  800.         (*d1)->d_name);
  801.     /* Is panic the right thing? */
  802.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  803.     }
  804.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  805.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  806.         (*d2)->d_name);
  807.     /* Is panic the right thing? */
  808.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  809.     }
  810.     return CtimeCompare(&attrs1, &attrs2);
  811. }
  812. #endif /* NOTDEF */
  813.  
  814. static int
  815. MtimeCompare(attrs1, attrs2)
  816.     struct    stat    *attrs1;
  817.     struct    stat    *attrs2;
  818. {
  819.     if (attrs1->st_mtime > attrs2->st_mtime) {
  820.     return -1;
  821.     }
  822.     if (attrs1->st_mtime < attrs2->st_mtime) {
  823.     return 1;
  824.     }
  825. #ifdef NOTDEF
  826.     if (attrs1->dataModifyTime.microseconds >
  827.         attrs2->dataModifyTime.microseconds) {
  828.     return -1;
  829.     }
  830.     if (attrs1->dataModifyTime.microseconds <
  831.         attrs2->dataModifyTime.microseconds) {
  832.     return 1;
  833.     }
  834. #endif /* NOTDEF */
  835.     return 0;
  836. }
  837.  
  838. static int
  839. FileMtimeSort(file1, file2)
  840.     FsflatFile    **file1;
  841.     FsflatFile    **file2;
  842. {
  843.     return MtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  844. }
  845.  
  846. static int
  847. FileMtimeReverseSort(file1, file2)
  848.     FsflatFile    **file1;
  849.     FsflatFile    **file2;
  850. {
  851.     return (-MtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  852. }
  853.  
  854. static    int
  855. MtimeSort(d1, d2)
  856.     struct    direct    **d1, **d2;
  857. {
  858.     struct    stat    attrs1;
  859.     struct    stat    attrs2;
  860.  
  861.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  862.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  863.         (*d1)->d_name);
  864.     /* Is panic the right thing? */
  865.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  866.     }
  867.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  868.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  869.         (*d2)->d_name);
  870.     /* Is panic the right thing? */
  871.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  872.     }
  873.     return MtimeCompare(&attrs1, &attrs2);
  874. }
  875.  
  876. static int
  877. DtimeCompare(attrs1, attrs2)
  878.     struct    stat    *attrs1;
  879.     struct    stat    *attrs2;
  880. {
  881.     if (attrs1->st_ctime > attrs2->st_ctime) {
  882.     return -1;
  883.     }
  884.     if (attrs1->st_ctime < attrs2->st_ctime) {
  885.     return 1;
  886.     }
  887. #ifdef NOTDEF
  888.     if (attrs1->st_ctime.microseconds > attrs2->st_ctime.microseconds) {
  889.     return -1;
  890.     }
  891.     if (attrs1->st_ctime.microseconds < attrs2->st_ctime.microseconds) {
  892.     return 1;
  893.     }
  894. #endif /* NOTDEF */
  895.     return 0;
  896. }
  897.  
  898. static int
  899. FileDtimeSort(file1, file2)
  900.     FsflatFile    **file1;
  901.     FsflatFile    **file2;
  902. {
  903.     return DtimeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  904. }
  905.  
  906. static int
  907. FileDtimeReverseSort(file1, file2)
  908.     FsflatFile    **file1;
  909.     FsflatFile    **file2;
  910. {
  911.     return (-DtimeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  912. }
  913.  
  914. static    int
  915. DtimeSort(d1, d2)
  916.     struct    direct    **d1, **d2;
  917. {
  918.     struct    stat    attrs1;
  919.     struct    stat    attrs2;
  920.  
  921.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  922.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  923.         (*d1)->d_name);
  924.     /* Is panic the right thing? */
  925.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  926.     }
  927.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  928.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  929.         (*d2)->d_name);
  930.     /* Is panic the right thing? */
  931.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  932.     }
  933.     return DtimeCompare(&attrs1, &attrs2);
  934. }
  935.  
  936. static int
  937. SizeCompare(attrs1, attrs2)
  938.     struct    stat    *attrs1;
  939.     struct    stat    *attrs2;
  940. {
  941.     if (attrs1->st_size > attrs2->st_size) {
  942.     return 1;
  943.     }
  944.     if (attrs1->st_size < attrs2->st_size) {
  945.     return -1;
  946.     }
  947.     return 0;
  948. }
  949.  
  950. static int
  951. FileSizeSort(file1, file2)
  952.     FsflatFile    **file1;
  953.     FsflatFile    **file2;
  954. {
  955.     return SizeCompare((*file1)->attrPtr, (*file2)->attrPtr);
  956. }
  957.  
  958. static int
  959. FileSizeReverseSort(file1, file2)
  960.     FsflatFile    **file1;
  961.     FsflatFile    **file2;
  962. {
  963.     return (-SizeCompare((*file1)->attrPtr, (*file2)->attrPtr));
  964. }
  965.  
  966. static    int
  967. SizeSort(d1, d2)
  968.     struct    direct    **d1, **d2;
  969. {
  970.     struct    stat    attrs1;
  971.     struct    stat    attrs2;
  972.  
  973.     if (lstat((*d1)->d_name, &attrs1) != 0) {
  974.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  975.         (*d1)->d_name);
  976.     /* Is panic the right thing? */
  977.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  978.     }
  979.     if (lstat((*d2)->d_name, &attrs2) != 0) {
  980.     sprintf(fsflatErrorMsg, "Couldn't get attributes for %s.",
  981.         (*d2)->d_name);
  982.     /* Is panic the right thing? */
  983.     Sx_Panic(fsflatDisplay, fsflatErrorMsg);
  984.     }
  985.     return SizeCompare(&attrs1, &attrs2);
  986. }
  987.  
  988.  
  989. /*
  990.  *----------------------------------------------------------------------
  991.  *
  992.  * FsflatGetCompareProc --
  993.  *
  994.  *    Figure out what the comparison routine is and return it in
  995.  *    the compareProc parameter.
  996.  *    If fileProcP is true, return a function that takes pointers
  997.  *    to FsflatFiles.  Otherwise it takes struct    direct's.
  998.  *
  999.  * Results:
  1000.  *    None.
  1001.  *
  1002.  * Side effects:
  1003.  *    None.
  1004.  *
  1005.  *----------------------------------------------------------------------
  1006.  */
  1007. void
  1008. FsflatGetCompareProc(aWindow, compareProcPtr, fileProcP)
  1009.     FsflatWindow    *aWindow;
  1010.     int    (**compareProcPtr)();
  1011.     Boolean        fileProcP;    /* which comp func type */
  1012. {
  1013.     if (aWindow->sortingInstructions == 0) {
  1014.     aWindow->sortingInstructions = FSFLAT_ALPHA_SORT;    /* default */
  1015.     }
  1016.     if (aWindow->sortingInstructions & FSFLAT_REVERSE_SORT) {
  1017.     if (aWindow->sortingInstructions & FSFLAT_ALPHA_SORT) {
  1018.         if (fileProcP) {
  1019.         *compareProcPtr = FileAlphaReverseSort;
  1020.         } else {
  1021.         *compareProcPtr = AlphaReverse;
  1022.         }
  1023.     } else if (aWindow->sortingInstructions & FSFLAT_ATIME_SORT) {
  1024.         if (fileProcP) {
  1025.         *compareProcPtr = FileAtimeReverseSort;
  1026.         } else {
  1027.         *compareProcPtr = AtimeReverse;
  1028.         }
  1029. #ifdef NOTDEF
  1030.     } else if (aWindow->sortingInstructions & FSFLAT_CTIME_SORT) {
  1031.         if (fileProcP) {
  1032.         *compareProcPtr = FileCtimeReverseSort;
  1033.         } else {
  1034.         *compareProcPtr = CtimeReverse;
  1035.         }
  1036. #endif NOTDEF
  1037.     } else if (aWindow->sortingInstructions & FSFLAT_MTIME_SORT) {
  1038.         if (fileProcP) {
  1039.         *compareProcPtr = FileMtimeReverseSort;
  1040.         } else {
  1041.         *compareProcPtr = MtimeReverse;
  1042.         }
  1043.     } else if (aWindow->sortingInstructions & FSFLAT_DTIME_SORT) {
  1044.         if (fileProcP) {
  1045.         *compareProcPtr = FileDtimeReverseSort;
  1046.         } else {
  1047.         *compareProcPtr = DtimeReverse;
  1048.         }
  1049.     } else if (aWindow->sortingInstructions & FSFLAT_SIZE_SORT) {
  1050.         if (fileProcP) {
  1051.         *compareProcPtr = FileSizeReverseSort;
  1052.         } else {
  1053.         *compareProcPtr = SizeReverse;
  1054.         }
  1055.     }
  1056.     } else {
  1057.     if (aWindow->sortingInstructions & FSFLAT_ALPHA_SORT) {
  1058.         if (fileProcP) {
  1059.         *compareProcPtr = FileAlphaSort;
  1060.         } else {
  1061.         *compareProcPtr = AlphaForwards;
  1062.         }
  1063.     } else if (aWindow->sortingInstructions & FSFLAT_ATIME_SORT) {
  1064.         if (fileProcP) {
  1065.         *compareProcPtr = FileAtimeSort;
  1066.         } else {
  1067.         *compareProcPtr = AtimeForwards;
  1068.         }
  1069. #ifdef NOTDEF
  1070.     } else if (aWindow->sortingInstructions & FSFLAT_CTIME_SORT) {
  1071.         if (fileProcP) {
  1072.         *compareProcPtr = FileCtimeSort;
  1073.         } else {
  1074.         *compareProcPtr = CtimeForwards;
  1075.         }
  1076. #endif /* NOTDEF */
  1077.     } else if (aWindow->sortingInstructions & FSFLAT_MTIME_SORT) {
  1078.         if (fileProcP) {
  1079.         *compareProcPtr = FileMtimeSort;
  1080.         } else {
  1081.         *compareProcPtr = MtimeForwards;
  1082.         }
  1083.     } else if (aWindow->sortingInstructions & FSFLAT_DTIME_SORT) {
  1084.         if (fileProcP) {
  1085.         *compareProcPtr = FileDtimeSort;
  1086.         } else {
  1087.         *compareProcPtr = DtimeForwards;
  1088.         }
  1089.     } else if (aWindow->sortingInstructions & FSFLAT_SIZE_SORT) {
  1090.         if (fileProcP) {
  1091.         *compareProcPtr = FileSizeSort;
  1092.         } else {
  1093.         *compareProcPtr = SizeForwards;
  1094.         }
  1095.     }
  1096.     }
  1097.  
  1098.     return;
  1099. }
  1100.